/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.gui.dao;

import br.gui.interfaces.DAOInterface;
import br.gui.interfaces.IdAutoIncrement;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 *
 * @author Monique
 */
public class DAOMaster<T> implements DAOInterface<T> {

    private Class<T> classePersistente; 
    
    public DAOMaster() {
        
    }

   

    /**
     * Usa o nome da classe do objeto que vai ser persistido para gerar o Id
     * automaticamente e depois adiciona o objeto a sua respectiva lista no
     * container.
     */
    @SuppressWarnings("unchecked")
    @Override
    public void persist(T obj) {
//        this.classePersistente = (Class<T>) ((ParameterizedType) (getClass()
//                .getGenericSuperclass())).getActualTypeArguments()[0];
        Type t = getClass().getGenericSuperclass();
        t = ((ParameterizedType) ((Class) t).getGenericSuperclass()).getActualTypeArguments()[0];
        Class type = (Class) t;

            
        if (obj instanceof IdAutoIncrement) {
            ((IdAutoIncrement) obj).setId(Container.getInstance().gerarId(obj.getClass().getName()));
        }

        Container.getInstance().getList(type.getName()).add(obj);
    }

    /**
     * Usa o nome da classe do objeto a ser removido para remover o objeto da
     * sua respectiva lista no container.
     */
    @SuppressWarnings("unchecked")
    public void remove(T obj) {
        Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Container.getInstance().getList(type.getName()).remove(obj);
    }

    /**
     * Atualiza o objeto na sua respectiva lista no container usando o Id do
     * objeto. A lista é escolhida através do nome da classe.
     *
     * @return O objeto que foi atualizado
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public T merge(T obj) {
        List lista = Container.getInstance().getList(obj.getClass().getName());
        int index = lista.indexOf(findById(((IdAutoIncrement) obj).getId()));
        lista.set(index, obj);

        return null;
    }

    /**
     * Atualiza o objeto na memoria de acordo com o mesmo objeto no arquivo.
     */
    public void refresh(T obj) {
        /*
         * Implementar caso precise.
         */
    }

    /**
     * Salva o container no arquivo.
     */
    public void commit() {
        Container.saveFile();
    }

    /**
     * Sobrescreve o container da memoria pelo container do arquivo.
     */
    public void rollback() {
        Container.openFile();
    }

    /**
     * Retorna todos os objetos do tipo do DAO
     *
     * @return Lista com todos os objetos do tipo da classe parametrizada no DAO
     */
    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        return Container.getInstance().getList(type.getName());
    }

    /**
     * Encontra um objeto pelo Id
     *
     * @param id Id do objeto que deseja achar
     * @return O objeto encontrado. Retorna null se o objeto não existir na
     * lista.
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public T findById(int id) {
        Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        List lista = Container.getInstance().getList(type.getName());
        for (Object obj : lista) {
            if (((IdAutoIncrement) obj).getId() == id) {
                return (T) obj;
            }

        }

        return null;
    }

    /**
     * Encontrado o ultimo objeto persistido
     *
     * @return O ultimo objeto persistido
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public T findLast() {
        Class<T> type = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        List lista = Container.getInstance().getList(type.getName());
        return (T) lista.get(lista.size() - 1);

    }
}
